require 'active_support'

# Represents a skin (a look & feel for the front-end of the website), which is
# essentially a directory of templates under <tt>/vendor/skins/</tt>.
# The interface is vaguely ActiveRecord-like (but read-only).
class Skin

  cattr_accessor :skin_path
  
  @@skin_path = "#{RAILS_ROOT}/vendor/skins"
  
  attr_reader :dir, :name

  def initialize(name)
    @name = name
    @dir = Dir.new("#{skin_path}/#{name}")
  end
  
  # The full path to the template for the given action.
  # If this skin does not implement a template for this action, the appropriate
  # default template path is returned.
  def template(controller, action)
    # TODO: Make this work for other template types (not just rhtml).
    #        <aybe we should just search for name.* and use the first
    #        file that matches?
    if FileTest.exist? file = "#{@dir.path}/templates/#{controller}/#{action}.rhtml"
      file
    else
      "#{RAILS_ROOT}/app/views/#{controller}/#{action}.rhtml"
    end
  end
  
  # The full path to the CSS template with the given name.
  # If this skin does not implement this stylesheet, the
  # default stylesheet for the given name is returned.
  def stylesheet(name)
    if FileTest.exists? file = "#{dir.path}/css/#{name}.css"
      file
    else
      "#{RAILS_ROOT}/app/views/stylesheets/#{name}.css"
    end
  end
  
  # The full path to the image with the given name.
  # If this skin does not implement this image, the
  # default image for the given name is returned.
  def image(filename)
    if FileTest.exists? file = "#{dir.path}/images/#{filename}"
      file
    else
      "#{RAILS_ROOT}/app/views/stylesheets/#{name}.css"
    end
  end
    
  # FIXME: we can't do skin-specific layouts, because Rails doesn't
  #        support layouts outside of the /app/views/layouts directory :(      
  # The full path to this skin's layout.
  # If the skin does not implement a layout, the default Rails layout at 
  # <tt>/app/views/layouts/blog.rhtml</tt> is returned.
#  def layout
#    if FileTest.exist? file = "#{@dir.path}/layout"
#      file
#    else
#      "blog"
#    end
#  end
  
  
  # Get an instance of Skin for the skin with the given name.
  def self.find(name)
    if FileTest.exists? "#{skin_path}/#{name}"
      Skin.new(name)
    else
      raise SkinNotFound, "There is no skin named '#{name}' in #{skin_path}."
    end
  end
  
  # Get an array of Skin objects for all of the available skins.
  # Sorted alphabetically by name.
  def self.find_all
    skindir = Dir.new(skin_path)
    skins = []
    skindir.each do |name|
      if FileTest.directory? "#{skin_path}/#{name}"
        skins << Skin.new(name)
      end
    end
    
    skins
  end
  
  # Raised when you try to get a skin that doesn't exist.
  class SkinNotFound < Exception
  end
end